package com.ygqh.baby.service.wechat.service.impl;

import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.ygqh.baby.ao.AppType;
import com.ygqh.baby.ao.PayType;
import com.ygqh.baby.ao.SalesPlatform;
import com.ygqh.baby.constant.Constant;
import com.ygqh.baby.model.YgOrderInfoModel;
import com.ygqh.baby.po.YgOrderPayment;
import com.ygqh.baby.po.YgProduct;
import com.ygqh.baby.po.YgUser;
import com.ygqh.baby.service.*;
import com.ygqh.baby.service.wechat.api.GoodApi;
import com.ygqh.baby.service.wechat.model.good.*;
import com.ygqh.baby.service.wechat.service.WeixinGoodService;
import com.ygqh.baby.template.AbstractSplitListTemplate;
import com.ygqh.baby.utils.MailUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 微信好物圈接口实现
 *
 * @Author: sunshuo
 * @Date: 2019/5/22 09:58
 * @Version: 1.0
 */
@Service
public class WeixinGoodServiceImpl implements WeixinGoodService {

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private YgOrderService ygOrderService;
	@Autowired
	private YgUserService ygUserService;
	@Autowired
	private YgUserAuthsService ygUserAuthsService;
	@Autowired
	private YgOrderPaymentService ygOrderPaymentService;
	@Autowired
	private WxSmallAuthorityService wxSmallAuthorityService;
	@Autowired
	private MailUtil mailUtil;
	@Autowired
	private YgProductService ygProductService;

	@Override
	public void importOrder(Long orderId, int isHistory, GoodImportOrderRequestParam.ImportOrderAction action) {
		importOrder(ygOrderService.findOrderInfo(orderId, null), isHistory, action);
	}

	@Override
	public void importOrder(YgOrderInfoModel order, int isHistory,
							GoodImportOrderRequestParam.ImportOrderAction action) {
		importOrderBatch(Collections.singletonList(order), isHistory, action);
	}

	@Override
	public void importOrderBatch(List<YgOrderInfoModel> orderInfoList, int isHistory,
								 GoodImportOrderRequestParam.ImportOrderAction action) {
		if (CollectionUtils.isEmpty(orderInfoList)) {
			return;
		}
		Map<String, List<YgOrderInfoModel>> collect =
				orderInfoList.stream().collect(Collectors.groupingBy(YgOrderInfoModel::getPlatformNo));
		collect.forEach((platformNo, orderList) -> processYgOrder(platformNo, orderInfoList, isHistory, action));
	}

	@Override
	public void importProduct(Long productId) {
		YgProduct product = ygProductService.findDetailById(productId);
		importProduct(product);
	}

	@Override
	public void importProduct(YgProduct product) {
		importProduct(Collections.singletonList(product));
	}

	@Override
	public void importProduct(List<YgProduct> productList) {
		if (CollectionUtils.isEmpty(productList)) {
			return;
		}
		List<YgProduct> listForYijiadian = productList.stream()
				.filter(o -> o.getSalesPlatform().contains(SalesPlatform.Yijiadian.name()))
				.collect(Collectors.toList());
		processYgProduct(Constant.YIJIADIAN_PLATFORM_NO, listForYijiadian);
		List<YgProduct> listForYiigoo = productList.stream()
				.filter(o -> o.getSalesPlatform().contains(SalesPlatform.Yiigoo.name()))
				.collect(Collectors.toList());
		processYgProduct(Constant.YIIGOO_PLATFORM_NO, listForYiigoo);
	}

    @Override
    public void importProductByIds(List<Long> productIdList) {
        if (CollectionUtils.isEmpty(productIdList)) {
        	return;
		}
        importProduct(ygProductService.findDetailById(productIdList));
	}

    private void processYgProduct(String platformNo, List<YgProduct> productList) {
		if (CollectionUtils.isEmpty(productList)) {
			return;
		}
		List<GoodProduct> goodProductList = new ArrayList<>();
		productList.forEach(product -> goodProductList.addAll(processYgProduct(product)));
		new AbstractSplitListTemplate<GoodProduct>(goodProductList, 10) {
			@Override
			public int execute(List<GoodProduct> recordList) {
				pushGoodProduct(platformNo, recordList);
				return recordList.size();
			}
		}.split();
	}

	private void pushGoodProduct(String platformNo, List<GoodProduct> productList) {
		TokenHolder tokenHolder = wxSmallAuthorityService.findTokenHolder(platformNo);
		GoodApi api = new GoodApi(tokenHolder);
		GoodImportProductRequestParam requestParam = new GoodImportProductRequestParam();
		requestParam.setProductList(productList);
		try {
			GoodImportProductResult result = api.importProduct(requestParam);
			if (!result.isSuccess()) {
				throw new WeixinException(result.getCode() + "", result.getDesc());
			}
			System.out.println("微信好物圈推送物品成功");
		} catch (WeixinException e) {
			List<String> collect = productList.stream().map(GoodProduct::getItemCode).collect(Collectors.toList());
			mailUtil.simpleSend("sunshuo@yiigoo.com", "微信好物圈推送物品异常",
					"微信好物圈推送物品错误，productIds=" + collect.toString() + "，" + e.getMessage());
			logger.error(e.getMessage(), e);
			if (e.getErrorCode().equals("40001 invalid credential")) {
				try {
					tokenHolder.refreshToken();
				} catch (WeixinException e1) {
					logger.error(e.getMessage(), e);
				}
			}
		}
	}

	private List<GoodProduct> processYgProduct(YgProduct productInfo) {
		return GoodProductBuilder.builder(productInfo).build().splitSku(16);
	}

	private void processYgOrder(String platformNo, List<YgOrderInfoModel> orderInfoList, int isHistory,
								GoodImportOrderRequestParam.ImportOrderAction action) {
		List<GoodOrder> orderList = new ArrayList<>();
		orderInfoList.forEach(order -> {
			try {
				GoodOrder goodOrder = processYgOrder(order);
				if (StringUtils.isNotBlank(goodOrder.getExtInfo().getUserOpenId())) {
					orderList.add(goodOrder);
				}
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		});
		new AbstractSplitListTemplate<GoodOrder>(orderList, 10) {
			@Override
			public int execute(List<GoodOrder> recordList) {
				pushGoodOrder(platformNo, recordList, isHistory, action);
				return recordList.size();
			}
		}.split();
	}

	private void pushGoodOrder(String platformNo, List<GoodOrder> orderList, int isHistory,
							   GoodImportOrderRequestParam.ImportOrderAction action) {
		TokenHolder tokenHolder = wxSmallAuthorityService.findTokenHolder(platformNo);
		GoodApi api = new GoodApi(tokenHolder);
		GoodImportOrderRequestParam requestParam = new GoodImportOrderRequestParam();
		requestParam.setOrderList(orderList);
		requestParam.setAction(action);
		requestParam.setIsHistory(isHistory);
		try {
			GoodImportOrderResult result = api.importOrder(requestParam);
			if (!result.isSuccess()) {
				throw new WeixinException(result.getCode() + "", result.getDesc() + ": " + result.getFailOrderList());
			}
			System.out.println("微信好物圈推送订单成功");
		} catch (WeixinException e) {
			List<String> collect = orderList.stream().map(GoodOrder::getOrderId).collect(Collectors.toList());
			mailUtil.simpleSend("sunshuo@yiigoo.com", "微信好物圈推送订单异常",
					"微信好物圈推送订单错误，orderIds=" + collect + "，" + e.getMessage());
			logger.error(e.getMessage(), e);
			if (e.getErrorCode().equals("40001 invalid credential")) {
				try {
					tokenHolder.refreshToken();
				} catch (WeixinException e1) {
					logger.error(e.getMessage(), e);
				}
			}
		}
	}

	private GoodOrder processYgOrder(YgOrderInfoModel orderInfo) {
		if (Constant.YIIGOO_PLATFORM_NO.equals(orderInfo.getPlatformNo())) {
			if (AppType.Small.equals(orderInfo.getAppType())) {
				YgUser user = ygUserService.findById(orderInfo.getUserId());
				orderInfo.setOpenId(user.getSmallOpenId());
			}
		} else {
			String openId = ygUserAuthsService.
					getOpenId(orderInfo.getUserId(), orderInfo.getPlatformNo(), orderInfo.getAppType());
			orderInfo.setOpenId(openId);
		}
		YgOrderPayment payment = ygOrderPaymentService.findByOrderId(orderInfo.getOrderId());
		String transId;
		if (payment != null && StringUtils.isNotBlank(payment.getTransactionId())) {
			transId = payment.getTransactionId();
		} else {
			orderInfo.setPayType(PayType.Account);
			transId = null;
		}
		return GoodOrderBuilder.builder(orderInfo).build().setTransId(transId).get();
	}
}
